package edu.bbu.commonproject.backend.db.services.mongodb;

import com.mongodb.BasicDBObject;
import com.mongodb.DBCollection;
import com.mongodb.DBObject;
import com.mongodb.MongoException;

import edu.bbu.commonproject.backend.db.exceptions.DataBaseErrorException;
import edu.bbu.commonproject.backend.db.exceptions.UserConflictException;
import edu.bbu.commonproject.backend.db.factory.mongodb.MongoDBDAOFactory;
import edu.bbu.commonproject.backend.db.model.DBUser;
import edu.bbu.commonproject.backend.db.services.UserDAOServices;

/**
 * The mongoDB user services.
 */
public class MongoDBUserDAOServices implements UserDAOServices
{
	/**
	 * Inserting a new user into database.
	 */
	public void insertNewUser(DBUser user) throws UserConflictException, DataBaseErrorException
	{
		if(isExistingUser(user))
		{
			throw new UserConflictException(user.getUserName() + " already in use.");
		}
		else 
		{
			try
			{
				BasicDBObject newUserObject = new BasicDBObject();
				
				newUserObject.put("UserName", user.getUserName());
				newUserObject.put("Password", user.getUserPasword());
				
				MongoDBDAOFactory.dataBase.getCollection("RegistredUsers").insert(newUserObject);
			}
			catch (MongoException e)
			{
				throw new DataBaseErrorException("Error occured on database, when creating a new user.");
			}
			
			
		}
	}
	
	/**
	 * Getting the user data model.
	 */
	public DBUser getUser(String userName) throws UserConflictException, DataBaseErrorException
	{
		DBUser user = new DBUser(userName, "");
		
		if(!isExistingUser(user))
		{
			throw new UserConflictException(userName + " not exists in database.");
		}
		else 
		{
			try
			{			
				BasicDBObject queryDbObject = new BasicDBObject();
				queryDbObject.put("UserName", userName);
				
				DBObject searchedUserDBObject = MongoDBDAOFactory.dataBase.getCollection("RegistredUsers").findOne(queryDbObject);
				
				return new DBUser((String) searchedUserDBObject.get("UserName"), (String) searchedUserDBObject.get("Password"));
			}
			catch (MongoException e)
			{
				throw new DataBaseErrorException("Error occured on database, when getting the user data.");
			}
			
		}
	}
	
	/**
	 * Check if the user name already exists or not.
	 */
	public boolean isExistingUser(DBUser user)
	{
		BasicDBObject queryDbObject = new BasicDBObject();
		queryDbObject.put("UserName", user.getUserName());
		
		DBObject searchedUserDbObject = MongoDBDAOFactory.dataBase.getCollection("RegistredUsers").findOne(queryDbObject);
		
		if(searchedUserDbObject != null)
		{
			return searchedUserDbObject.containsField("UserName");
		}
		
		return false;
	}
	
	/**
	 * Getting the specified users password.
	 */
	public String getPassword(DBUser user) throws UserConflictException, DataBaseErrorException
	{
		if(!isExistingUser(user))
		{
			throw new UserConflictException(user.getUserName() + " not exists in database.");
		}
		else 
		{
			try
			{
				BasicDBObject queryDbObject = new BasicDBObject();
				queryDbObject.put("UserName", user.getUserName());
				
				DBObject searchedUserDbObject = MongoDBDAOFactory.dataBase.getCollection("RegistredUsers").findOne(queryDbObject);
				
				if(searchedUserDbObject != null)
				{
					return (String) searchedUserDbObject.get("Password");
				}
				else 
				{
					throw new UserConflictException(user.getUserName() + " not exists in database.");
				}
			}
			catch (MongoException e)
			{
				throw new DataBaseErrorException("Error occured on database, when getting the user password.");
			}
		}
	}
	
	/**
	 * Overwrite the specified users password.
	 */
	public void editUserPassword(DBUser user, String newPassword) throws UserConflictException, DataBaseErrorException
	{
		if(!isExistingUser(user))
		{
			throw new UserConflictException(user.getUserName() + " not exists in database.");
		}
		else 
		{
			try
			{
				BasicDBObject updateDbObject = new BasicDBObject();
				updateDbObject.put("$set", new BasicDBObject("Password", newPassword));
				
				MongoDBDAOFactory.dataBase.getCollection("RegistredUsers").update(new BasicDBObject("UserName", user.getUserName()), updateDbObject);
			}
			catch (MongoException e)
			{
				throw new DataBaseErrorException("Error occured on database, when editing user password.");
			}
		}
		
	}
	
	/**
	 * Delete the specified user from the database.
	 * The delete operation will be executed on the users files too.
	 * This operation is not reversible.
	 */
	public void deleteUser(DBUser user) throws UserConflictException, DataBaseErrorException
	{
		if(!isExistingUser(user))
		{
			throw new UserConflictException(user.getUserName() + " not exists in database.");
		}
		else 
		{
			try
			{			
				BasicDBObject queryDbObject = new BasicDBObject();
				queryDbObject.put("UserName", user.getUserName());
				
				MongoDBDAOFactory.dataBase.getCollection("RegistredUsers").remove(queryDbObject);
				
				MongoDBDAOFactory.dataBase.getCollection(user.getUserName() + ".chunks").drop();
				MongoDBDAOFactory.dataBase.getCollection(user.getUserName() + ".files").drop();
				MongoDBDAOFactory.dataBase.getCollection(user.getUserName() + ".directories").drop();
			}
			catch (MongoException e)
			{
				throw new DataBaseErrorException("Error occured on database, when deleting user account.");
			}
		}
		
	}
}
